1時間プログラミング 009 はてブで最近ブックマークしたエントリーを表示する
#1時間プログラミング
概要
はてブで最近ブックマークしたエントリーを表示する
ブックマークトップページの1ページ目に表示されるものが対象
privateなブックマークは対象外
所要時間: 1時間
使い方
code:terminal
$ deno run --allow-net mod.ts
GitHub - b-fuze/deno-dom: Browser DOM & HTML parser in Deno / https://github.com/b-fuze/deno-dom
Web Scraping with Deno | ScrapingAnt / https://scrapingant.com/blog/deno-web-scraping
サーバダウンしたニコニコ漫画に何が起きていたのか - BOOK☆WALKER Tech Blog / https://developers.bookwalker.jp/entry/2022/10/28/110000
ここさえ抑えればGitHub API v4がわかる! GraphQL入門 / https://zenn.dev/hsaki/articles/github-graphql
NestJSのDIコンテナで作るクリーンなレイヤー境界 / https://speakerdeck.com/kimutyam/nestjsfalsedikontenatezuo-rukurinnareiyajing-jie
神戸駅前「毒キノコ」大量発生の謎 取材後に体験した「見事なオチ」 / https://withnews.jp/article/f0221025000qq000000000000000W0i810101qq000025194A
Mac で画面を収録する方法 - Apple サポート / https://support.apple.com/ja-jp/HT208721
NestJS の基礎概念の図解と要約 / https://zenn.dev/morinokami/articles/nestjs-overview
GitHub - conwnet/github1s: One second to read GitHub code with VS Code. / https://github.com/conwnet/github1s
Effective Deno / https://zenn.dev/uki00a/books/effective-deno
GitHub - softprops/atty: are you or are you not a tty? / https://github.com/softprops/atty
RustのTUIライブラリtui-rsの基本 - Qiita / https://qiita.com/GreasySlug/items/3d12e4f0eeb07778718a
GitHub - fdehau/tui-rs: Build terminal user interfaces and dashboards using Rust / https://github.com/fdehau/tui-rs
AtCoder高橋社長がLINEのコーディング試験を見て驚いた理由―。「競プロとこんなに違うとは……」 / https://gaishishukatsu.com/archives/191528
【Slay the Spire】サイト内のスレスパ攻略記事まとめ+紹介 | BaskMedia / https://baskmedia.jp/slaythespire-matome/
Deno / https://deno.land/
Optional parameters in Rust – Vidify / https://vidify.org/blog/rust-parameters/
【中央揃え編】CSS限界オタクと学ぶレイアウトCSSサンプル集 - Qiita / https://qiita.com/mhousetree/items/9a3265c0d6d6e903ed46
ソフトウェアアーキテクチャ・ハードパーツ / https://www.oreilly.co.jp//books/9784814400065/
舞台で生きていく――「劇場版 少女☆歌劇 レヴュースタァライト」の舞台少女たちが高らかに響かせた独立宣言 / https://www.4gamer.net/games/424/G042449/20211217162/
実装
はてブAPIを使いたかったが、エントリー一覧を取得するようなAPIは存在しない
となると、スクレイピングの出番
自分のブックマークトップページからエントリーを抽出する
1ページ目に表示されるブックマークのみを対象とする
privateなブックマークは対象外
今回はTS(Deno)で作成する
を参考に進める
ブックマークトップページのHTMLを取得する
code:ts
const fetchHatebuHtml = async (id: string): Promise<string> => {
const url = https://b.hatena.ne.jp/${id}/bookmark;
const resp = await fetch(url);
return resp.text();
};
HTMLをパースしてエントリー一覧を取得する
パースにはdeno-domを使用した
code:ts
type HatebuEntry = {
url: string;
text: string;
};
const parseHatebuHtml = (html: string): HatebuEntry[] => {
const doc = new DOMParser().parseFromString(html, "text/html")!;
const entryList = Array.from(
doc.querySelectorAll(".bookmark-item"),
) as Element[];
return entryList.map((elm) => {
const titleElem = elm.querySelector(".centerarticle-entry-title a")!;
const url = titleElem.getAttribute("href")!;
const text = titleElem.textContent;
return { url, text };
});
};
querySelectorAll()ではNodeList型が返る(型引数は指定できない)
今回はNodeではなくElementが必要なので、型を強制的に変換している
エントリー一覧を出力する
code:ts
const printHatebuEntryList = (entryList: HatebuEntry[]) => {
entryList.forEach((ent) => {
console.log(${ent.text} / ${ent.url});
});
};
感想
deno-domではquerySelectAll()に型引数を指定できないので、そこで少し手間取った